#define _GNU_SOURCE     //在源文件开头定义_GNU_SOURCE宏
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <signal.h>
#include <termios.h> 
#include <sys/types.h>   
#include <sys/time.h>   
#include <sys/stat.h>   
#include <fcntl.h>   
#include <unistd.h>   
#include <errno.h>   
#include <stdlib.h>   
#include <string.h>   
#include <sys/ipc.h>
#include <sys/shm.h>
#include <linux/joystick.h>   
//#include <linux/list.h> /*郁闷，不能直接使用linux自带的list链表，需要单独提取出来，见前面的code*/   
#include "../include/listop.h"   
#include "../include/device.h"   

#if 1   
#define LOG_DBG(fmt, ...)  fprintf(stdout, fmt, ##__VA_ARGS__)   
#else   
#define LOG_DBG(fmt, ...)   
#endif   
  
#define LOG_ERR(fmt, ...)  fprintf(stderr, fmt, ##__VA_ARGS__)   

void uart_init(int fd){
    struct termios old_cfg;
    if(0>tcgetattr(fd,&old_cfg))
    {
	    LOG_ERR("uart connection error\n");
	    return ;
    }

    struct termios new_cfg;

    memset(&new_cfg,0x0,sizeof(struct termios));

    //配置为原始模式
    cfmakeraw(&new_cfg);

    //使能接收
    new_cfg.c_cflag |= CREAD;

    //设置波特率
    cfsetspeed(&new_cfg,B115200);

    //设置数据位大小
    new_cfg.c_cflag &= ~CSIZE;
    new_cfg.c_cflag |= CS8;//数据位为8位

    //设置奇偶校验


    //奇校验使能
    new_cfg.c_cflag |= (PARODD | PARENB);
    new_cfg.c_iflag |= INPCK;
    //偶校验使能
    new_cfg.c_cflag |= PARENB;
    new_cfg.c_cflag &= ~PARODD; /* 清除 PARODD 标志，配置为偶校验 */
    new_cfg.c_iflag |= INPCK;
    //无校验
    new_cfg.c_cflag &= ~PARENB;
    new_cfg.c_iflag &= ~INPCK;

    //设置停止位
    // 将停止位设置为一个比特
    new_cfg.c_cflag &= ~CSTOPB;
    // 将停止位设置为 2 个比特
    new_cfg.c_cflag |= CSTOPB;

    //设置MIN和TIME的值
    new_cfg.c_cc[VTIME] = 0;
    new_cfg.c_cc[VMIN] = 0;
    
    //调用tcflush（）清空缓冲区
    tcflush(fd, TCIOFLUSH);
    
    //调用tcsetattr()将配置写入设备，使其立即生效
    tcsetattr(fd,TCSANOW,&new_cfg);

}

uint8_t uart_rx_buf[32];

void* pthread_device_data(void * arg)		//创建线程用以接收数据
{
    int uartfd = *(int *)arg;
    Dev_Sta_Data dev_sta_data;
    Report_Exc report_exec;
    uint8_t *data_buf =  (uint8_t *) &dev_sta_data;
    uint32_t count = 0;
    bool get_frame_flag = false;
    time_t t;
    struct tm  *timenow;
    FILE  *file_fd = NULL;
    char outfile[128];
    key_t record_key , report_key;                                        
    int shm_id_record,shm_id_report;                                      
    char *record_buf ,*report_buf;                                    
    int ret;                                       
     //获取key                                      
    if((record_key = ftok("/home/linjunhan/dolphin/record_data",0xf)) < 0)                    
         perror("ftok");                                                                 
     //创建或获取共享内存                               
    if((shm_id_record = shmget(record_key,SHMSIZE,IPC_CREAT|0666)) < 0)
         perror("shmget");                                                                                                 
     //映射共享内存到进程的虚拟空间                        
    if((record_buf = shmat(shm_id_record,NULL,0)) < 0)                   
         perror("shmat");                                            

    //获取key                                      
    if((report_key = ftok("/home/linjunhan/dolphin/report",0xe)) < 0)                    
         perror("ftok");                                                                 
     //创建或获取共享内存                               
    if((shm_id_report = shmget(report_key,SHMSIZE,IPC_CREAT|0666)) < 0)
         perror("shmget");                                                                                                 
     //映射共享内存到进程的虚拟空间                        
    if((report_buf = shmat(shm_id_report,NULL,0)) < 0)                   
         perror("shmat");                   

    t = time(NULL);                                                                                                                                                       

    while(1)
    {
        ret = read(uartfd, uart_rx_buf,32);     //一次最多读32个字节数据
        if(ret != 0){        
            if(uart_rx_buf[0] == NANO_FRAME_HEAD_LOW && uart_rx_buf[1] == NANO_FRAME_HEAD_HIGH ){
                get_frame_flag = true;
                count = 0;
            }
            if(get_frame_flag){
                for(int i = 0; i < 32; ++i){
                    *(data_buf + i + 32*count) = uart_rx_buf[i];
                }
                count++;
                if(count*32 > DEV_FRAME_LEN){
                    // printf("motor speed: %.2f dps   motor curr:  %.2f A  motor degree:  %.2f ° \r\n",dev_sta_data.motor_sta.motor_spd,dev_sta_data.motor_sta.motor_curr, dev_sta_data.motor_sta.motor_degree);
                    // printf("accx is :%.3f   accy is :%.3f   accz is :%.3f \r\n",dev_sta_data.sensor_sta.imu1.SAcc[0],dev_sta_data.sensor_sta.imu1.SAcc[1], dev_sta_data.sensor_sta.imu1.SAcc[2]);
                    printf("%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.2f, %.2f, %.2f\n",dev_sta_data.sensor_sta.imu0.SAngle[0],dev_sta_data.sensor_sta.imu0.SAngle[1], dev_sta_data.sensor_sta.imu0.SAngle[2],dev_sta_data.sensor_sta.imu0.SGyro[0],dev_sta_data.sensor_sta.imu0.SGyro[1], dev_sta_data.sensor_sta.imu0.SGyro[2],dev_sta_data.sensor_sta.imu0.SAcc[0],dev_sta_data.sensor_sta.imu0.SAcc[1], dev_sta_data.sensor_sta.imu0.SAcc[2],dev_sta_data.sensor_sta.imu1.SAngle[0],dev_sta_data.sensor_sta.imu1.SAngle[1], dev_sta_data.sensor_sta.imu1.SAngle[2],dev_sta_data.sensor_sta.imu1.SGyro[0],dev_sta_data.sensor_sta.imu1.SGyro[1], dev_sta_data.sensor_sta.imu1.SGyro[2],dev_sta_data.sensor_sta.imu1.SAcc[0],dev_sta_data.sensor_sta.imu1.SAcc[1], dev_sta_data.sensor_sta.imu1.SAcc[2],dev_sta_data.motor_sta.motor_spd,dev_sta_data.motor_sta.motor_curr,dev_sta_data.motor_sta.motor_vol);
                    printf("battery elec is: %d  volt is:%.2f   temperature is:%.2f  \n",dev_sta_data.sensor_sta.battery.elec,dev_sta_data.sensor_sta.battery.volt,dev_sta_data.sensor_sta.battery.temp); 
                    
                    if(dev_sta_data.sensor_sta.leak){
                        report_exec.leak = 1;
                        //printf("leak detected is: %d\n",dev_sta_data.sensor_sta.leak);
                    }
                    else{
                        report_exec.leak = 0;
                    }
                        
                    if(dev_sta_data.sensor_sta.battery.elec < 30){
                        //printf("battery elec is less than 30\n");
                        report_exec.elec = 1;
                    }
                    else{
                        report_exec.elec = 0;
                    }
                    get_frame_flag = false;
                }
            }
        }

        if(strcmp(record_buf,"record") == 0){
            system("sudo espeak -v zh  '开始记录数据' -s 220");
            timenow=localtime(&t);
            strftime(outfile, 128, "/home/linjunhan/dolphin/record_data/data_%Y%m%d_%H:%M:%S.csv", timenow);
            file_fd = fopen(outfile,"w+");
            fprintf(file_fd,"\n%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n","Time","AngleX(imu0)","AngleY(imu0)","AngleZ(imu0)","GyroX(imu0)","GyroY(imu0)","GyroZ(imu0)","AccX(imu0)","AccY(imu0)","AccZ(imu0)","AngleX(imu1)","AngleY(imu1)","AngleZ(imu1)","GyroX(imu1)","GyroY(imu1)","GyroZ(imu1)","AccX(imu1)","AccY(imu1)","AccZ(imu1)","Motor_Spd","Motor_Curr","Motor_Volt");
           // fprintf(file_fd,"\n%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n","Time","AngleX(imu1)","AngleY(imu1)","AngleZ(imu1)","GyroX(imu1)","GyroY(imu1)","GyroZ(imu1)","AccX(imu1)","AccY(imu1)","AccZ(imu1)","Motor_Spd","Motor_Curr","Motor_Volt");
            while(strcmp(record_buf,"record") == 0){
                ret = read(uartfd, uart_rx_buf,32);     //一次最多读32个字节数据
                if(ret != 0){        
                if(uart_rx_buf[0] == NANO_FRAME_HEAD_LOW && uart_rx_buf[1] == NANO_FRAME_HEAD_HIGH ){
                    get_frame_flag = true;
                    count = 0;
                }
                if(get_frame_flag){
                    for(int i = 0; i < 32; ++i){
                        *(data_buf + i + 32*count) = uart_rx_buf[i];
                    }
                    count++;
                    if(count*32 > DEV_FRAME_LEN){
                        time(&t);
                        timenow  = localtime(&t);
                        char szTmp[50] = {0}; 
                        strftime(szTmp,50,"%H:%M:%S",timenow);
                        //fprintf(file_fd,"%s,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.2f, %.2f, %.2f\n",szTmp,dev_sta_data.sensor_sta.imu1.SAngle[0],dev_sta_data.sensor_sta.imu1.SAngle[1], dev_sta_data.sensor_sta.imu1.SAngle[2],dev_sta_data.sensor_sta.imu1.SGyro[0],dev_sta_data.sensor_sta.imu1.SGyro[1], dev_sta_data.sensor_sta.imu1.SGyro[2],dev_sta_data.sensor_sta.imu1.SAcc[0],dev_sta_data.sensor_sta.imu1.SAcc[1], dev_sta_data.sensor_sta.imu1.SAcc[2],dev_sta_data.motor_sta.motor_spd,dev_sta_data.motor_sta.motor_curr,dev_sta_data.motor_sta.motor_vol);
                        fprintf(file_fd,"%s,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.2f, %.2f, %.2f\n",szTmp,dev_sta_data.sensor_sta.imu0.SAngle[0],dev_sta_data.sensor_sta.imu0.SAngle[1], dev_sta_data.sensor_sta.imu0.SAngle[2],dev_sta_data.sensor_sta.imu0.SGyro[0],dev_sta_data.sensor_sta.imu0.SGyro[1], dev_sta_data.sensor_sta.imu0.SGyro[2],dev_sta_data.sensor_sta.imu0.SAcc[0],dev_sta_data.sensor_sta.imu0.SAcc[1], dev_sta_data.sensor_sta.imu0.SAcc[2],dev_sta_data.sensor_sta.imu1.SAngle[0],dev_sta_data.sensor_sta.imu1.SAngle[1], dev_sta_data.sensor_sta.imu1.SAngle[2],dev_sta_data.sensor_sta.imu1.SGyro[0],dev_sta_data.sensor_sta.imu1.SGyro[1], dev_sta_data.sensor_sta.imu1.SGyro[2],dev_sta_data.sensor_sta.imu1.SAcc[0],dev_sta_data.sensor_sta.imu1.SAcc[1], dev_sta_data.sensor_sta.imu1.SAcc[2],dev_sta_data.motor_sta.motor_spd,dev_sta_data.motor_sta.motor_curr,dev_sta_data.motor_sta.motor_vol);
                        if(dev_sta_data.sensor_sta.leak){
                        report_exec.leak = 1;
                        printf("leak detected is: %d\n",dev_sta_data.sensor_sta.leak);
                    }
                    else{
                        report_exec.leak = 0;
                    }
                        
                    if(dev_sta_data.sensor_sta.battery.elec < 30){
                        //printf("battery elec is less than 30\n");
                        report_exec.elec = 1;
                    }
                    else{
                        report_exec.elec = 0;
                    }
                         get_frame_flag = false;
                    }
                }
                }
                memset(uart_rx_buf,0,32);
                memcpy(report_buf,(uint8_t *)&report_exec,SHMSIZE);
                //usleep(1000);
                }
                fclose(file_fd);
                system("sudo espeak -v zh  '停止记录数据' -s 220");
            }
        //usleep(1000);
        memcpy(report_buf,(uint8_t *)&report_exec,SHMSIZE);
    }
    
}


int main(int argc, char* argv[])  
{  
    struct termios old_cfg;
    int  uartfd = open("/dev/myuart",O_RDWR|O_NOCTTY| O_NDELAY);
    while(0>tcgetattr(uartfd,&old_cfg))
    {
        close(uartfd); 
	    perror("open uart error\n");
	    sleep(5);
        uartfd = open("/dev/myuart",O_RDWR|O_NOCTTY| O_NDELAY);
    }
    uart_init(uartfd);
    printf("set up uart success\n");
  

    write(uartfd, "\n",1); 
    write(uartfd, "nano_ctr\n",10); 

    pthread_t tid;
    pthread_create(&tid, NULL, pthread_device_data, &uartfd);
    while(1){
        sleep(10);
    }
}
